import { asyncExecFunction } from "@/king-components/js/KingonPlus";
import POSConst from "./POSTConst";
import POSConnect from "./POSConnect";
import { formatMoney } from "@/utils/util";
import { getBuffetOrderDetail, netPrinterPrinting } from "@/api";
import { useStore } from "vuex";
import { cashiersTemplate } from "./template";
const store = useStore();
/**
 * 打印工具
 */
const calculateMaxChars = (paperWidth: number, charWidth: number, charSpacing: number) => {
  return Math.floor(paperWidth / (charWidth + charSpacing));
};

// 示例参数 (用于计算 一行的字符数量)
const paperWidthInPixels = 384; // 纸张宽度（像素）
const charWidthInPixels = 10; // 字符宽度（像素）
const charSpacingInPixels = 2; // 字符间距（像素）

// 计算一行最大可容纳字符数量（考虑字符间距）
const maxCharsPerLenght = calculateMaxChars(paperWidthInPixels, charWidthInPixels, charSpacingInPixels);

// 生成线条的方法
export const generateLine = (maxCharsPerLine = maxCharsPerLenght) => {
  // 生成由连字符组成的线条
  const line = "-".repeat(maxCharsPerLine);
  return line;
};

/**
 * 创建打印内容(特殊 用于 goodslist.xx)
 * @param res
 * @param keyUsed 只有当字段为 x.xx 格式时，才需要 keyUsed
 * @returns
 */
const goodslistCreator = (res: any, keyUsed: string[]) => {
  const printCtrl = [];
  if (Array.isArray(keyUsed) && keyUsed.length > 0) {
    /* 5. 菜品 */

    // 菜品名称列长度
    const mealNameLength = 9;
    // 菜品数量列长度
    const numberLength = 4;
    // 金额列长度
    const priceLength = 5;
    // 小计列长度
    const totelLength = 5;

    // 打印分割线
    printCtrl.push({ ActionType: "PrintText", Parameter: generateLine() });
    // 菜品列表 - 表头
    printCtrl.push({
      ActionType: "PrintText",
      Parameter: `${keyUsed.includes("foodName") ? completeLength("菜品", mealNameLength, false, " ") : ""}${
        keyUsed.includes("foodName") ? completeLength("数量", numberLength, false, " ") : ""
      } ${keyUsed.includes("foodName") ? completeLength("金额", priceLength, false, " ") : ""} ${
        keyUsed.includes("foodName") ? completeLength("小计", totelLength, false, " ") : ""
      } \r\n`,
    });
    // 菜品列表 - 内容

    res.goodslist.map((v: any) => {
      printCtrl.push({
        ActionType: "PrintText",
        Parameter: `${completeLength(v.foodName, 6, true)}  ${completeLength(v.number, 4, false)}    ${completeLength(
          Number(v.price).toFixed(2),
          5,
          false
        )}  ${completeLength(Number(v.totel).toFixed(2), 5, false)}\r\n`,
      });
    });
  } else {
    /* 5. 菜品 */
    // 打印分割线
    printCtrl.push({ ActionType: "PrintText", Parameter: generateLine() });
    // 菜品列表 - 表头
    printCtrl.push({ ActionType: "PrintText", Parameter: `菜品        数量   金额   小计\r\n` });
    // 菜品列表 - 内容

    res.goodslist.map((v: any) => {
      printCtrl.push({
        ActionType: "PrintText",
        Parameter: `${completeLength(v.foodName, 6, true)}  ${completeLength(v.number, 4, false)}    ${completeLength(
          Number(v.price).toFixed(2),
          5,
          false
        )}  ${completeLength(Number(v.totel).toFixed(2), 5, false)}\r\n`,
      });
    });
  }

  return printCtrl;
};

// 字段打印配置
// 注意： Parameter 和 ActionType 必填
const fieldsPrintCreator = [
  {
    key: "merchname",
    // value: '商户名称', // 默认取字段值，如果非空则取该值
    creator: (res: any) => {
      const printCtrl = [];
      /* 1. 标题 */
      // 打印商家名称
      printCtrl.push({
        ActionType: "PrintText",
        Parameter: res.merchname || "-",
        Config: {
          alignment: POSConst.ALIGNMENT_CENTER, // 居中对齐
          textSize: POSConst.TXT_2HEIGHT | POSConst.TXT_2WIDTH, // 字体大小为2号
        },
      });
      return printCtrl;
    },
  },
  {
    key: "custom-title",
    // value: '自定义标题', // 默认取字段值，如果非空则取该值
    creator: (res: any) => {
      const printCtrl = [];
      /* 2. 自定义标题 */
      // 打印商家名称
      printCtrl.push({
        ActionType: "PrintText",
        Parameter: res["custom-title"] || "-",
        Config: {
          alignment: POSConst.ALIGNMENT_CENTER, // 居中对齐
          textSize: POSConst.TXT_2HEIGHT | POSConst.TXT_2WIDTH, // 字体大小为2号
        },
      });
      return printCtrl;
    },
  },
  {
    key: "orderNo",
    creator: (res: any) => {
      const printCtrl = [];
      printCtrl.push({ ActionType: "PrintText", Parameter: "订单号：" + res.orderNo });
      return printCtrl;
    },
  },
  {
    key: "opuser",
    creator: (res: any) => {
      const printCtrl = [];
      // 打印收银员
      printCtrl.push({ ActionType: "PrintText", Parameter: `收银员：${res.opuser}` });
      return printCtrl;
    },
  },
  {
    key: "time",
    creator: (res: any) => {
      const printCtrl = [];
      // 打印下单时间
      printCtrl.push({ ActionType: "PrintText", Parameter: `下单时间：${res.time}` });
      return printCtrl;
    },
  },
  // {
  //   // 分栏打印 （分栏打印必定执行）
  //   key: "__division__",
  //   creator: (res: any) => {
  //     const printCtrl = [];
  //     printCtrl.push({ ActionType: "PrintText", Parameter: generateLine() });
  //     return printCtrl;
  //   },
  // },
  {
    key: "goodslist",
    creator: (res: any) => {
      const printCtrl = [];
      /* 5. 菜品 */
      // 打印分割线
      printCtrl.push({ ActionType: "PrintText", Parameter: generateLine() });
      // 菜品列表 - 表头
      printCtrl.push({ ActionType: "PrintText", Parameter: `菜品        数量   金额   小计` });
      // 菜品列表 - 内容

      res.goodslist?.map((v: any) => {
        printCtrl.push({
          ActionType: "PrintText",
          Parameter: `${completeLength(v.foodName, 6, true)}  ${completeLength(v.number, 4, false)}    ${completeLength(
            Number(v.price).toFixed(2),
            5,
            false
          )}  ${completeLength(Number(v.totel).toFixed(2), 5, false)}`,
        });
      });
      return printCtrl;
    },
  },
  // {
  //   key: "goodslist.foodName",
  //   creator: goodslistCreator,
  // },
  // {
  //   key: "goodslist.number",
  //   creator: goodslistCreator,
  // },
  // {
  //   key: "goodslist.price",
  //   creator: goodslistCreator,
  // },
  // {
  //   key: "goodslist.totel",
  //   creator: goodslistCreator,
  // },

  {
    key: "remark",
    creator: (res: any) => {
      const printCtrl = [];
      // 备注
      printCtrl.push({ ActionType: "PrintText", Parameter: `备注：${res.remark}` });
      return printCtrl;
    },
  },
  {
    key: "fee",
    creator: (res: any) => {
      const printCtrl = [];
      // 打印合计金额
      printCtrl.push({ ActionType: "PrintText", Parameter: `金额合计：￥${res.fee}` });
      /* 打印分割线 */
      printCtrl.push({ ActionType: "PrintText", Parameter: generateLine() });
      return printCtrl;
    },
  },
  {
    key: "subsidies",
    creator: (res: any) => {
      const printCtrl = [];
      // 打印优惠信息
      if (res.subsidies) {
        printCtrl.push({ ActionType: "PrintText", Parameter: `补贴：-￥${res.subsidies}` });
      }
      return printCtrl;
    },
  },
  {
    key: "discount",
    creator: (res: any) => {
      const printCtrl = [];
      if (res.discount) {
        printCtrl.push({ ActionType: "PrintText", Parameter: `会员折扣：-￥${res.discount}` });
      }
      return printCtrl;
    },
  },
  {
    key: "total",
    creator: (res: any) => {
      const printCtrl = [];
      /* 8. 应收合计（算上优惠） */
      printCtrl.push({ ActionType: "PrintText", Parameter: `应收合计：￥${res.fee}` });
      printCtrl.push({ ActionType: "PrintText", Parameter: "" });
      return printCtrl;
    },
  },
  {
    key: "foot",
    creator: (res: any) => {
      const printCtrl = [];
      // 备注
      printCtrl.push({
        ActionType: "PrintText",
        Parameter: `欢迎下次光临！`,
        Config: {
          alignment: POSConst.ALIGNMENT_CENTER, // 居中对齐
        },
      });
      return printCtrl;
    },
  },
  {
    key: "custom-foot",
    // value: '自定义底', // 默认取字段值，如果非空则取该值
    creator: (res: any) => {
      const printCtrl = [];
      // 备注
      printCtrl.push({
        ActionType: "PrintText",
        Parameter: res["custom-foot"],
        Config: {
          alignment: POSConst.ALIGNMENT_CENTER, // 居中对齐
        },
      });
      return printCtrl;
    },
  },
];

interface Template {
  useFields: string[];
  type: string;
  id: number;
  fixedConfig?: {
    name: string;
    fixed: string;
  };
}

/**
 * 打印订单
 * @param res 订单信息
 * @param temp 打印模板信息
 * @returns
 */
export const printorder = (res: any, temp: Template) => {
  const temFields = temp.useFields;
  const printCtrl = [];
  if (temFields && Array.isArray(temFields) && temFields.length > 0) {
    for (const creator of fieldsPrintCreator) {
      if (!temFields.includes(creator.key)) continue;

      // 如果 temp 设定了固定值（fixedValue）, 则赋值对应 res[key] 的值
      if (Array.isArray(temp.fixedConfig) && temp.fixedConfig.length > 0) {
        const fixedtor = temp.fixedConfig.find((item) => item.name === creator.key);
        if (fixedtor) res[creator.key] = fixedtor.fixed;
      }

      // 特殊情况 creator.key 为 字符串表示的对象字段类型 如 "goodslist.foodName"
      if (creator.key.includes(".")) {
        // // 这里值判断 单层对象字段 暂时不支持多层嵌套
        // const trueKeys = creator.key.split(".")[1];
        // if (!temp.includes(trueKey)) continue;
        // const printCode = creator.creator(res, [trueKey]);
        // // console.log("creator printCode > ",printCode)
        // if (Array.isArray(printCode) && printCode.length > 0) printCtrl.push(...printCode);
      } else {
        const printCode = creator.creator(res);
        // console.log("creator printCode > ",printCode)
        if (Array.isArray(printCode) && printCode.length > 0) printCtrl.push(...printCode);
      }
    }
  } else {
    // 默认打印所有字段
    for (const creator of fieldsPrintCreator) {
      const printCode = creator.creator(res);
      if (Array.isArray(printCode) && printCode.length > 0) printCtrl.push(...printCode);
    }
  }

  // 在 printCtrl 第一个和最后一个插入换行 （不同打印设备的情况可能不同）
  // 1. 最初那台白色设备 YF_029E 的（小票机） 需要换行
  if (/* printDeviceType === "YF_029E" */ true) {
    printCtrl.unshift({ ActionType: "PrintText", Parameter: "\n" });
    printCtrl.push({ ActionType: "PrintText", Parameter: "\n" });
  }

  return {
    source: printCtrl,
    data: JSON.stringify({ PrintData: printCtrl }),
  };
};

export const printStart = async (Arg: any) => {
  console.log(`一行最多可以容纳 ${maxCharsPerLenght} 个字符（考虑字符间距）`);
  uni.showToast({ title: "打印中...", icon: "none" });

  try {
    // 打印
    console.log("最后的Arg = ", Arg);
    // const result = await asyncExecFunction("HnXfjPrinte", Arg);
    // 创建连接 (不传 DeviePath 默认连接第一个)
    const createResult = await asyncExecFunction("KoCreatePrinter", {
      DeviceType: POSConnect.DEVICE_TYPE_USB,
    });
    // 打印票据
    const printResult = await asyncExecFunction("koPrintReceipt", Arg);
    uni.showToast({
      title: "小票已打印完成",
      icon: "none",
    });
    console.log("打印SDK 返回", { createResult, printResult });
  } catch (error) {
    console.error("打印失败", error);
    uni.showToast({
      title: "小票打印失败",
      icon: "none",
    });
  }
};

/** 指定设备进行打印 */
export const printStartByDevice = async (Arg: any, DevicePath: string) => {
  // uni.showToast({ title: "打印中...", icon: "none" });

  if (DevicePath) {
    try {
      // 修改 Arg 添加设备id参数
      const editArg = JSON.parse(Arg);
      // editArg.DeviceId = DevicePath;
      editArg.DeviceType = POSConnect.DEVICE_TYPE_USB;
      editArg.DevicePath = DevicePath;
      Arg = JSON.stringify(editArg);
    } catch (error) {
      console.error("修改Arg失败", error);
    }
  }

  try {
    // 打印
    console.log("最后的Arg = ", Arg);
    // 创建连接（KoCreatePrinter 同一个未断开连接的设备无需重复连接，这里是保证多设备打印的情况）
    const createResult = await asyncExecFunction("KoCreatePrinter", {
      DeviceType: POSConnect.DEVICE_TYPE_USB,
      DevicePath: DevicePath,
    });
    console.log("createResult>", createResult);
    // 打印票据
    const printResult = await asyncExecFunction("koPrintReceipt", Arg);
    // const result = await asyncExecFunction("HnXfjPrinterUsbPrintByDeviceId", Arg);
    uni.showToast({
      title: "小票已打印完成",
      icon: "none",
    });
    console.log("打印SDK 返回", printResult);
  } catch (error) {
    console.error("打印失败", error);
    uni.showToast({
      title: "小票打印失败",
      icon: "none",
    });
  }
};

// （偏业务）下单完成后根据系统配置，选择打印机批量打印
export const orderPrintTick = async (buffetOrderId: string) => {
  console.log("orderPrintTick 执行任务");
  try {
    // 查询打印机配置, 参数为 1 则开启打印， 2 为关闭打印
    const { frontDeskPrinting, rearKitchenPrinting } = store.getters.printModule;
    // 计算打印次数 （当前只有一个打印机，如多打印机，需要根据打印机备注的位置打印）
    let printCount = 0;
    [frontDeskPrinting, rearKitchenPrinting].map((v) => {
      if (v == 1) printCount++;
    });
    if (printCount == 0) return;

    // 商家信息
    const { abbreviation } = store.getters.businessInfo;

    // 使用订单id 查询订单详细
    const { data: orderDetails } = await getBuffetOrderDetail({ buffetOrderId: buffetOrderId });

    if (orderDetails.buffetOrderId) {
      // 触发网络打印
      netPrinterPrinting(orderDetails.buffetOrderId)
        .then(({ success, data, msg }) => {
          if (!success) console.error("网络打印失败", { success, data, msg });
        })
        .catch((err) => {
          console.error("网络打印失败", err);
        });
    }

    const goodslist = orderDetails.buffetOrderItemEntityList.map((v: any) => {
      return {
        foodName: v.foodName,
        number: v.foodNum,
        price: formatMoney(/* v.memberPrice || */ v.price),
        totel: formatMoney(/* v.memberPrice ||  */ v.price * v.foodNum),
      };
    });

    const discount = totalDiscount(orderDetails.buffetOrderItemEntityList);

    const res = {
      orderNo: orderDetails.buffetOrderId,
      merchname: abbreviation,
      opuser: "默认收银员", // TODO 目前没有收银员登录账号，都是登录商家账号
      time: orderDetails.createTime,
      goodslist: goodslist,
      remark: getRemark(orderDetails.buffetOrderItemEntityList),
      fee: formatMoney(orderDetails.amountcollected),
      subsidies: formatMoney(orderDetails.mealAllowance),
      discount: formatMoney(discount),
      total: formatMoney(orderDetails.amountcollected),
    };

    // 打印设备错误数量
    let errcount = 0;

    if (frontDeskPrinting == 1) {
      // 查询打印设置(获取前台后台打印当前模板参数)
      // 将订单信息以固定参数格式处理，输出打印SDK可用的JSON数据
      const temp = store.getters.currentFrontTemplate;
      const printInstance = printorder(res, temp);
      // 查询本地设备列表中类型为 后厨 打印的设备
      const frontDevices = store.getters.usbPrinterListFront;
      if (Array.isArray(frontDevices) && frontDevices.length > 0) {
        // 下单打印小票 需要根据 【打印设置】 中的设备需要打印的设备类型，再从
        // 本地设备列表中获取对应类型的设备id，然后调用打印接口
        for (const device of frontDevices) {
          try {
            await printStartByDevice(printInstance.data, device.path);
          } catch (error) {
            console.error(`设备 ${device.name} 打印小票失败`, error);
            errcount = errcount + 1;
          }
        }
      } else {
        // 打印
        await printStart(printInstance.data);
      }
    }

    if (rearKitchenPrinting == 1) {
      // 查询打印设置(获取前台后台打印当前模板参数)
      // 将订单信息以固定参数格式处理，输出打印SDK可用的JSON数据
      const temp = store.getters.currentRearTemplate;
      const printInstance = printorder(res, temp);
      // 查询本地设备列表中类型为 后厨 打印的设备
      const rearKitchenDevices = store.getters.usbPrinterListRear;
      if (Array.isArray(rearKitchenDevices) && rearKitchenDevices.length > 0) {
        // 下单打印小票 需要根据 【打印设置】 中的设备需要打印的设备类型，再从
        // 本地设备列表中获取对应类型的设备id，然后调用打印接口
        for (const device of rearKitchenDevices) {
          try {
            await printStartByDevice(printInstance.data, device.path);
          } catch (error) {
            console.error(`设备 ${device.name} 打印小票失败`, error);
            errcount = errcount + 1;
          }
        }
      } else {
        // 打印
        await printStart(printInstance.data);
      }
    }

    if (errcount > 0) uni.showToast({ title: `有${errcount}台设备打印小票失败`, icon: "none" });
  } catch (error) {
    console.warn("toPrintTick 打印小票失败", error);
  }
};

export const noOrderPrintTick = async (info: any) => {

  if (info.buffetOrderId) {
    //  触发网络打印 
    netPrinterPrinting(info.buffetOrderId)
      .then(({ success, data, msg }) => {
        if (!success) console.error("网络打印失败", { success, data, msg });
      })
      .catch((err) => {
        console.error("网络打印失败", err);
      });
  }

  const templateData = cashiersTemplate.find(v => v.id == 1002);
  const printerData = printorder(info, templateData);
  await printStart(printerData.data);
}

/** 循环购物车列表整合备注信息 */
const getRemark = (list: any) => {
  if (!Array.isArray(list) || list.length == 0) return "";
  return list
    .map((v) => {
      return `${v.foodName}: ${v.remark};`;
    })
    .join("\n");
};
// 加算总的会员优惠
const totalDiscount = (goodsList: any) => {
  console.log("会员优惠计算", goodsList);
  if (!goodsList || !Array.isArray(goodsList)) return 0;
  return goodsList.reduce((pre, cur) => {
    let discount = cur.memberPrice ? (cur.price - cur.memberPrice) * cur.foodNum : 0;
    return pre + discount;
  }, 0);
};

/**
 * 按长度处理文本
 * @param str
 * @param length
 * @param ellipsis
 * @param replaceText
 * @returns
 */
export const completeLength = (str: string, length: number, ellipsis?: boolean, replaceText = "."): string => {
  if (str.length == length) return str;
  if (str.length > length) return str.substring(0, length - 1) + (ellipsis ? replaceText : "");
  if (str.length < length) return str + Array.from({ length: length - str.length }, () => " ").join(" ");
  return str;
};
